λ³΅ν© μ»΄ν¬λνΈ, λμ 컨ν μ€νΈ, 볡μ‘ν μν κ΄λ¦¬λ₯Ό μν μ±λ₯ μ΅μ ν κΈ°λ² λ± React Context APIμ κ³ κΈ ν¨ν΄μ νμν©λλ€.
μν κ΄λ¦¬λ₯Ό μν κ³ κΈ React Context API ν¨ν΄
React Context APIλ prop λλ¦΄λ§ μμ΄ μ ν리μΌμ΄μ μ 체μμ μνλ₯Ό 곡μ ν μ μλ κ°λ ₯ν λ©μ»€λμ¦μ μ 곡ν©λλ€. κΈ°λ³Έμ μΈ μ¬μ©λ²μ κ°λ¨νμ§λ§, κ·Έ μ μ¬λ ₯μ μ΅λν νμ©νλ €λ©΄ 볡μ‘ν μν κ΄λ¦¬ μλ리μ€λ₯Ό μ²λ¦¬ν μ μλ κ³ κΈ ν¨ν΄μ μ΄ν΄ν΄μΌ ν©λλ€. μ΄ κΈμμλ μ΄λ¬ν ν¨ν΄ λͺ κ°μ§λ₯Ό μ΄ν΄λ³΄κ³ , μ¬λ¬λΆμ React κ°λ° μμ€μ ν λ¨κ³ λμΌ μ μλ μ€μ©μ μΈ μμ μ μ€ν κ°λ₯ν μΈμ¬μ΄νΈλ₯Ό μ 곡ν©λλ€.
κΈ°λ³Έ Context APIμ νκ³ μ΄ν΄νκΈ°
κ³ κΈ ν¨ν΄μ μ΄ν΄λ³΄κΈ° μ μ, κΈ°λ³Έ Context APIμ νκ³λ₯Ό μΈμ§νλ κ²μ΄ μ€μν©λλ€. κ°λ¨νκ³ μ μμ μΌλ‘ μ κ·Ό κ°λ₯ν μνμλ μ ν©νμ§λ§, μνκ° μμ£Ό λ³κ²½λλ 볡μ‘ν μ ν리μΌμ΄μ μμλ λ€λ£¨κΈ° μ΄λ ΅κ³ λΉν¨μ¨μ μΌ μ μμ΅λλ€. 컨ν μ€νΈλ₯Ό μ¬μ©νλ λͺ¨λ μ»΄ν¬λνΈλ 컨ν μ€νΈ κ°μ΄ λ³κ²½λ λλ§λ€ λ€μ λ λλ§λλλ°, μ΄λ ν΄λΉ μ»΄ν¬λνΈκ° μ λ°μ΄νΈλ νΉμ μν μ‘°κ°μ μμ‘΄νμ§ μλλΌλ λ§μ°¬κ°μ§μ λλ€. μ΄λ μ±λ₯ λ³λͺ© νμμΌλ‘ μ΄μ΄μ§ μ μμ΅λλ€.
ν¨ν΄ 1: 컨ν μ€νΈλ₯Ό νμ©ν λ³΅ν© μ»΄ν¬λνΈ(Compound Components)
λ³΅ν© μ»΄ν¬λνΈ ν¨ν΄μ 컨ν μ€νΈλ₯Ό ν΅ν΄ μμμ μΌλ‘ μνμ λ‘μ§μ 곡μ νλ κ΄λ ¨ μ»΄ν¬λνΈ λͺ¨μμ λ§λ€μ΄ Context APIλ₯Ό ν₯μμν΅λλ€. μ΄ ν¨ν΄μ μ¬μ¬μ©μ±μ λμ΄κ³ μλΉμλ₯Ό μν APIλ₯Ό λ¨μνν©λλ€. μ΄λ₯Ό ν΅ν΄ 볡μ‘ν λ‘μ§μ κ°λ¨ν ꡬνμΌλ‘ μΊ‘μνν μ μμ΅λλ€.
μμ : ν μ»΄ν¬λνΈ
ν μ»΄ν¬λνΈλ₯Ό μλ‘ λ€μ΄ μ€λͺ
ν΄ λ³΄κ² μ΅λλ€. μ¬λ¬ κ³μΈ΅μ ν΅ν΄ propsλ₯Ό μ λ¬νλ λμ , Tab μ»΄ν¬λνΈλ€μ 곡μ λ 컨ν
μ€νΈλ₯Ό ν΅ν΄ μμμ μΌλ‘ ν΅μ ν©λλ€.
// TabContext.js
import React, { createContext, useContext, useState, ReactNode } from 'react';
interface TabContextType {
activeTab: string;
setActiveTab: (tab: string) => void;
}
const TabContext = createContext(undefined);
interface TabProviderProps {
children: ReactNode;
defaultTab: string;
}
export const TabProvider: React.FC = ({ children, defaultTab }) => {
const [activeTab, setActiveTab] = useState(defaultTab);
const value: TabContextType = {
activeTab,
setActiveTab,
};
return {children} ;
};
export const useTabContext = () => {
const context = useContext(TabContext);
if (!context) {
throw new Error('useTabContext must be used within a TabProvider');
}
return context;
};
// TabList.js
import React, { ReactNode } from 'react';
interface TabListProps {
children: ReactNode;
}
export const TabList: React.FC = ({ children }) => {
return {children};
};
// Tab.js
import React, { ReactNode } from 'react';
import { useTabContext } from './TabContext';
interface TabProps {
label: string;
children: ReactNode;
}
export const Tab: React.FC = ({ label, children }) => {
const { activeTab, setActiveTab } = useTabContext();
const isActive = activeTab === label;
const handleClick = () => {
setActiveTab(label);
};
return (
);
};
// TabPanel.js
import React, { ReactNode } from 'react';
import { useTabContext } from './TabContext';
interface TabPanelProps {
label: string;
children: ReactNode;
}
export const TabPanel: React.FC = ({ label, children }) => {
const { activeTab } = useTabContext();
const isActive = activeTab === label;
return (
{isActive && children}
);
};
// Usage
import { TabProvider, TabList, Tab, TabPanel } from './components/Tabs';
function App() {
return (
Tab 1
Tab 2
Tab 3
Content for Tab 1
Content for Tab 2
Content for Tab 3
);
}
export default App;
μ₯μ :
- μλΉμλ₯Ό μν λ¨μνλ API: μ¬μ©μλ
Tab,TabList,TabPanelμλ§ μ κ²½ μ°λ©΄ λ©λλ€. - μμμ μΈ μν 곡μ : μ»΄ν¬λνΈλ€μ΄ μλμΌλ‘ 곡μ μνμ μ κ·Όνκ³ μ λ°μ΄νΈν©λλ€.
- ν₯μλ μ¬μ¬μ©μ±:
Tabμ»΄ν¬λνΈλ λ€λ₯Έ 컨ν μ€νΈμμ μ½κ² μ¬μ¬μ©λ μ μμ΅λλ€.
ν¨ν΄ 2: λμ 컨ν μ€νΈ(Dynamic Contexts)
μ΄λ€ μλ리μ€μμλ μ»΄ν¬λνΈ νΈλ¦¬μ μμΉλ λ€λ₯Έ λμ μμΈμ λ°λΌ λ€λ₯Έ 컨ν μ€νΈ κ°μ΄ νμν μ μμ΅λλ€. λμ 컨ν μ€νΈλ₯Ό μ¬μ©νλ©΄ νΉμ 쑰건μ λ°λΌ λ¬λΌμ§λ 컨ν μ€νΈ κ°μ μμ±νκ³ μ 곡ν μ μμ΅λλ€.
μμ : λμ 컨ν μ€νΈλ₯Ό μ¬μ©ν ν λ§ μ μ©
μ¬μ©μμ μ νΈλλ μ ν리μΌμ΄μ μ νΉμ μΉμ μ λ°λΌ λ€λ₯Έ ν λ§λ₯Ό μ 곡νλ €λ ν λ§ μμ€ν μ μκ°ν΄ λ΄ μλ€. λΌμ΄νΈ ν λ§μ λ€ν¬ ν λ§λ‘ κ°λ¨ν μμ λ₯Ό λ§λ€ μ μμ΅λλ€.
// ThemeContext.js
import React, { createContext, useContext, useState, ReactNode } from 'react';
interface Theme {
background: string;
color: string;
}
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const defaultTheme: Theme = {
background: 'white',
color: 'black'
};
const darkTheme: Theme = {
background: 'black',
color: 'white'
};
const ThemeContext = createContext({
theme: defaultTheme,
toggleTheme: () => {}
});
interface ThemeProviderProps {
children: ReactNode;
}
export const ThemeProvider: React.FC = ({ children }) => {
const [isDarkTheme, setIsDarkTheme] = useState(false);
const theme = isDarkTheme ? darkTheme : defaultTheme;
const toggleTheme = () => {
setIsDarkTheme(!isDarkTheme);
};
const value: ThemeContextType = {
theme,
toggleTheme,
};
return {children} ;
};
export const useTheme = () => {
return useContext(ThemeContext);
};
// Usage
import { useTheme, ThemeProvider } from './ThemeContext';
function MyComponent() {
const { theme, toggleTheme } = useTheme();
return (
This is a themed component.
);
}
function App() {
return (
);
}
export default App;
μ΄ μμ μμ ThemeProviderλ isDarkTheme μνμ λ°λΌ λμ μΌλ‘ ν
λ§λ₯Ό κ²°μ ν©λλ€. useTheme ν
μ μ¬μ©νλ μ»΄ν¬λνΈλ€μ ν
λ§κ° λ³κ²½λ λ μλμΌλ‘ λ€μ λ λλ§λ©λλ€.
ν¨ν΄ 3: 볡μ‘ν μν κ΄λ¦¬λ₯Ό μν useReducerμ 컨ν
μ€νΈ κ²°ν©
볡μ‘ν μν λ‘μ§μ κ΄λ¦¬νκΈ° μν΄ Context APIμ useReducerλ₯Ό κ²°ν©νλ κ²μ νλ₯ν μ κ·Ό λ°©μμ
λλ€. useReducerλ μ‘μ
μ κΈ°λ°νμ¬ μνλ₯Ό μ
λ°μ΄νΈνλ ꡬ쑰νλ λ°©λ²μ μ 곡νλ©°, Context APIλ₯Ό μ¬μ©νλ©΄ μ΄ μνμ dispatch ν¨μλ₯Ό μ ν리μΌμ΄μ
μ 체μμ 곡μ ν μ μμ΅λλ€.
μμ : κ°λ¨ν ν μΌ λͺ©λ‘(Todo List)
// TodoContext.js
import React, { createContext, useContext, useReducer, ReactNode } from 'react';
interface Todo {
id: number;
text: string;
completed: boolean;
}
interface TodoState {
todos: Todo[];
}
type TodoAction =
| { type: 'ADD_TODO'; text: string }
| { type: 'TOGGLE_TODO'; id: number }
| { type: 'DELETE_TODO'; id: number };
interface TodoContextType {
state: TodoState;
dispatch: React.Dispatch;
}
const initialState: TodoState = {
todos: [],
};
const todoReducer = (state: TodoState, action: TodoAction): TodoState => {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, { id: Date.now(), text: action.text, completed: false }],
};
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map((todo) =>
todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
),
};
case 'DELETE_TODO':
return {
...state,
todos: state.todos.filter((todo) => todo.id !== action.id),
};
default:
return state;
}
};
const TodoContext = createContext(undefined);
interface TodoProviderProps {
children: ReactNode;
}
export const TodoProvider: React.FC = ({ children }) => {
const [state, dispatch] = useReducer(todoReducer, initialState);
const value: TodoContextType = {
state,
dispatch,
};
return {children} ;
};
export const useTodo = () => {
const context = useContext(TodoContext);
if (!context) {
throw new Error('useTodo must be used within a TodoProvider');
}
return context;
};
// Usage
import { useTodo, TodoProvider } from './TodoContext';
function TodoList() {
const { state, dispatch } = useTodo();
return (
{state.todos.map((todo) => (
-
{todo.text}
))}
);
}
function AddTodo() {
const { dispatch } = useTodo();
const [text, setText] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault();
dispatch({ type: 'ADD_TODO', text });
setText('');
};
return (
);
}
function App() {
return (
);
}
export default App;
μ΄ ν¨ν΄μ μν κ΄λ¦¬ λ‘μ§μ 리λμ λ΄μ μ€μ μ§μ€ννμ¬, λ‘μ§μ μΆλ‘ νκ³ ν μ€νΈνκΈ° μ½κ² λ§λλλ€. μ»΄ν¬λνΈλ€μ μνλ₯Ό μ§μ κ΄λ¦¬ν νμ μμ΄ μ‘μ μ λμ€ν¨μΉνμ¬ μνλ₯Ό μ λ°μ΄νΈν μ μμ΅λλ€.
ν¨ν΄ 4: useMemoμ useCallbackμ μ΄μ©ν 컨ν
μ€νΈ μ
λ°μ΄νΈ μ΅μ ν
μμ μΈκΈνλ―μ΄, Context APIμ ν΅μ¬ μ±λ₯ κ³ λ € μ¬ν μ€ νλλ λΆνμν 리λ λλ§μ
λλ€. useMemoμ useCallbackμ μ¬μ©νλ©΄ 컨ν
μ€νΈ κ°μ νμν λΆλΆλ§ μ
λ°μ΄νΈλκ³ ν¨μ μ°Έμ‘°κ° μμ μ μΌλ‘ μ μ§λλλ‘ λ³΄μ₯νμ¬ μ΄λ¬ν 리λ λλ§μ λ°©μ§ν μ μμ΅λλ€.
μμ : ν λ§ μ»¨ν μ€νΈ μ΅μ ν
// OptimizedThemeContext.js
import React, { createContext, useContext, useState, useMemo, useCallback, ReactNode } from 'react';
interface Theme {
background: string;
color: string;
}
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
const defaultTheme: Theme = {
background: 'white',
color: 'black'
};
const darkTheme: Theme = {
background: 'black',
color: 'white'
};
const ThemeContext = createContext({
theme: defaultTheme,
toggleTheme: () => {}
});
interface ThemeProviderProps {
children: ReactNode;
}
export const ThemeProvider: React.FC = ({ children }) => {
const [isDarkTheme, setIsDarkTheme] = useState(false);
const theme = isDarkTheme ? darkTheme : defaultTheme;
const toggleTheme = useCallback(() => {
setIsDarkTheme(!isDarkTheme);
}, [isDarkTheme]);
const value: ThemeContextType = useMemo(() => ({
theme,
toggleTheme,
}), [theme, toggleTheme]);
return {children} ;
};
export const useTheme = () => {
return useContext(ThemeContext);
};
μ€λͺ :
useCallbackμtoggleThemeν¨μλ₯Ό λ©λͺ¨μ΄μ μ΄μ ν©λλ€. μ΄λ₯Ό ν΅ν΄isDarkThemeκ° λ³κ²½λ λλ§ ν¨μ μ°Έμ‘°κ° λ³κ²½λλλ‘ λ³΄μ₯νμ¬,toggleThemeν¨μμλ§ μμ‘΄νλ μ»΄ν¬λνΈμ λΆνμν 리λ λλ§μ λ°©μ§ν©λλ€.useMemoλ 컨ν μ€νΈ κ°μ λ©λͺ¨μ΄μ μ΄μ ν©λλ€. μ΄λ₯Ό ν΅ν΄themeμ΄λtoggleThemeν¨μ μ€ νλκ° λ³κ²½λ λλ§ μ»¨ν μ€νΈ κ°μ΄ λ³κ²½λλλ‘ λ³΄μ₯νμ¬, λΆνμν 리λ λλ§μ λμ± λ°©μ§ν©λλ€.
useCallbackμ΄ μμΌλ©΄ toggleTheme ν¨μλ ThemeProviderκ° λ λλ§λ λλ§λ€ μ¬μμ±λμ΄ valueκ° λ³κ²½λκ³ , ν
λ§ μμ²΄κ° λ³κ²½λμ§ μμλλΌλ 컨ν
μ€νΈλ₯Ό μ¬μ©νλ λͺ¨λ μ»΄ν¬λνΈμμ 리λ λλ§μ΄ λ°μν©λλ€. useMemoλ μμ‘΄μ±(theme λλ toggleTheme)μ΄ λ³κ²½λ λλ§ μλ‘μ΄ valueκ° μμ±λλλ‘ λ³΄μ₯ν©λλ€.
ν¨ν΄ 5: 컨ν μ€νΈ μ λ ν°(Context Selectors)
컨ν μ€νΈ μ λ ν°λ₯Ό μ¬μ©νλ©΄ μ»΄ν¬λνΈκ° 컨ν μ€νΈ κ°μ νΉμ λΆλΆλ§ ꡬλ ν μ μμ΅λλ€. μ΄λ 컨ν μ€νΈμ λ€λ₯Έ λΆλΆμ΄ λ³κ²½λ λ λ°μνλ λΆνμν 리λ λλ§μ λ°©μ§ν©λλ€. `use-context-selector`μ κ°μ λΌμ΄λΈλ¬λ¦¬λ μ§μ ꡬνμ ν΅ν΄ μ΄λ₯Ό λ¬μ±ν μ μμ΅λλ€.
μ¬μ©μ μ μ 컨ν μ€νΈ μ λ ν° μμ
// useCustomContextSelector.js
import { useContext, useState, useRef, useEffect } from 'react';
function useCustomContextSelector(
context: React.Context,
selector: (value: T) => S
): S {
const value = useContext(context);
const [selected, setSelected] = useState(() => selector(value));
const latestSelector = useRef(selector);
latestSelector.current = selector;
useEffect(() => {
let didUnmount = false;
let lastSelected = selected;
const subscription = () => {
if (didUnmount) {
return;
}
const nextSelected = latestSelector.current(value);
if (!Object.is(lastSelected, nextSelected)) {
lastSelected = nextSelected;
setSelected(nextSelected);
}
};
// You would typically subscribe to context changes here. Since this is a simplified
// example, we'll just call subscription immediately to initialize.
subscription();
return () => {
didUnmount = true;
// Unsubscribe from context changes here, if applicable.
};
}, [value]); // Re-run effect whenever the context value changes
return selected;
}
export default useCustomContextSelector;
// ThemeContext.js (Simplified for brevity)
import React, { createContext, useState, ReactNode } from 'react';
interface Theme {
background: string;
color: string;
}
interface ThemeContextType {
theme: Theme;
setTheme: (newTheme: Theme) => void;
}
const ThemeContext = createContext(undefined);
interface ThemeProviderProps {
children: ReactNode;
initialTheme: Theme;
}
export const ThemeProvider: React.FC = ({ children, initialTheme }) => {
const [theme, setTheme] = useState(initialTheme);
const value: ThemeContextType = {
theme,
setTheme
};
return {children} ;
};
export const useThemeContext = () => {
const context = React.useContext(ThemeContext);
if (!context) {
throw new Error("useThemeContext must be used within a ThemeProvider");
}
return context;
};
export default ThemeContext;
// Usage
import useCustomContextSelector from './useCustomContextSelector';
import ThemeContext, { ThemeProvider, useThemeContext } from './ThemeContext';
function BackgroundComponent() {
const background = useCustomContextSelector(ThemeContext, (context) => context.theme.background);
return Background;
}
function ColorComponent() {
const color = useCustomContextSelector(ThemeContext, (context) => context.theme.color);
return Color;
}
function App() {
const { theme, setTheme } = useThemeContext();
const toggleTheme = () => {
setTheme({ background: theme.background === 'white' ? 'black' : 'white', color: theme.color === 'black' ? 'white' : 'black' });
};
return (
);
}
export default App;
μ΄ μμ μμ BackgroundComponentλ ν
λ§μ background μμ±μ΄ λ³κ²½λ λλ§ λ¦¬λ λλ§λκ³ , ColorComponentλ color μμ±μ΄ λ³κ²½λ λλ§ λ¦¬λ λλ§λ©λλ€. μ΄λ μ 체 컨ν
μ€νΈ κ°μ΄ λ³κ²½λ λ λ°μνλ λΆνμν 리λ λλ§μ λ°©μ§ν©λλ€.
ν¨ν΄ 6: μνμ μ‘μ λΆλ¦¬νκΈ°
κ·λͺ¨κ° ν° μ ν리μΌμ΄μ μ κ²½μ°, 컨ν μ€νΈ κ°μ μνμ©κ³Ό μ‘μ (λμ€ν¨μΉ ν¨μ)μ©μ λ κ°μ§ κ°λ³ 컨ν μ€νΈλ‘ λΆλ¦¬νλ κ²μ κ³ λ €ν΄ λ³΄μΈμ. μ΄λ μ½λ ꡬμ±κ³Ό ν μ€νΈ μ©μ΄μ±μ ν₯μμν¬ μ μμ΅λλ€.
μνμ μ‘μ 컨ν μ€νΈλ₯Ό λΆλ¦¬ν ν μΌ λͺ©λ‘ μμ
// TodoStateContext.js
import React, { createContext, useContext, useReducer, ReactNode } from 'react';
interface Todo {
id: number;
text: string;
completed: boolean;
}
interface TodoState {
todos: Todo[];
}
const initialState: TodoState = {
todos: [],
};
const TodoStateContext = createContext(initialState);
interface TodoStateProviderProps {
children: ReactNode;
}
export const TodoStateProvider: React.FC = ({ children }) => {
const [state] = useReducer(todoReducer, initialState);
return {children} ;
};
export const useTodoState = () => {
return useContext(TodoStateContext);
};
// TodoActionContext.js
import React, { createContext, useContext, Dispatch, ReactNode } from 'react';
type TodoAction =
| { type: 'ADD_TODO'; text: string }
| { type: 'TOGGLE_TODO'; id: number }
| { type: 'DELETE_TODO'; id: number };
const TodoActionContext = createContext | undefined>(undefined);
interface TodoActionProviderProps {
children: ReactNode;
}
export const TodoActionProvider: React.FC = ({children}) => {
const [, dispatch] = useReducer(todoReducer, initialState);
return {children} ;
};
export const useTodoDispatch = () => {
const dispatch = useContext(TodoActionContext);
if (!dispatch) {
throw new Error('useTodoDispatch must be used within a TodoActionProvider');
}
return dispatch;
};
// todoReducer.js
export const todoReducer = (state: TodoState, action: TodoAction): TodoState => {
switch (action.type) {
case 'ADD_TODO':
return {
...state,
todos: [...state.todos, { id: Date.now(), text: action.text, completed: false }],
};
case 'TOGGLE_TODO':
return {
...state,
todos: state.todos.map((todo) =>
todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
),
};
case 'DELETE_TODO':
return {
...state,
todos: state.todos.filter((todo) => todo.id !== action.id),
};
default:
return state;
}
};
// Usage
import { useTodoState, TodoStateProvider } from './TodoStateContext';
import { useTodoDispatch, TodoActionProvider } from './TodoActionContext';
function TodoList() {
const state = useTodoState();
return (
{state.todos.map((todo) => (
-
{todo.text}
))}
);
}
function TodoActions({ todo }) {
const dispatch = useTodoDispatch();
return (
<>
>
);
}
function AddTodo() {
const dispatch = useTodoDispatch();
const [text, setText] = React.useState('');
const handleSubmit = (e) => {
e.preventDefault();
dispatch({ type: 'ADD_TODO', text });
setText('');
};
return (
);
}
function App() {
return (
);
}
export default App;
μ΄λ¬ν λΆλ¦¬λ₯Ό ν΅ν΄ μ»΄ν¬λνΈλ νμν 컨ν
μ€νΈλ§ ꡬλ
νμ¬ λΆνμν 리λ λλ§μ μ€μΌ μ μμ΅λλ€. λν 리λμμ κ° μ»΄ν¬λνΈλ₯Ό κ°λ³μ μΌλ‘ λ¨μ ν
μ€νΈνκΈ°κ° λ μ¬μμ§λλ€. λν, νλ‘λ°μ΄λλ₯Ό κ°μΈλ μμκ° μ€μν©λλ€. ActionProviderκ° StateProviderλ₯Ό κ°μΈμΌ ν©λλ€.
λͺ¨λ² μ¬λ‘ λ° κ³ λ € μ¬ν
- 컨ν μ€νΈκ° λͺ¨λ μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬λ₯Ό λ체ν΄μλ μ λ©λλ€: λ§€μ° ν¬κ³ 볡μ‘ν μ ν리μΌμ΄μ μ κ²½μ° Reduxλ Zustandμ κ°μ μ μ© μν κ΄λ¦¬ λΌμ΄λΈλ¬λ¦¬κ° μ¬μ ν λ λμ μ νμΌ μ μμ΅λλ€.
- κ³Όλν 컨ν μ€νΈ μ¬μ© μ§μ: λͺ¨λ μν μ‘°κ°μ 컨ν μ€νΈμ λ£μ νμλ μμ΅λλ€. μ§μ μΌλ‘ μ μμ μ΄κ±°λ λ리 곡μ λλ μνμλ§ μ μ€νκ² μ»¨ν μ€νΈλ₯Ό μ¬μ©νμΈμ.
- μ±λ₯ ν μ€νΈ: νΉν μμ£Ό μ λ°μ΄νΈλλ μνλ₯Ό λ€λ£° λλ 컨ν μ€νΈ μ¬μ©μΌλ‘ μΈν μ±λ₯ μν₯μ νμ μΈ‘μ νμΈμ.
- μ½λ λΆν (Code Splitting): Context APIλ₯Ό μ¬μ©ν λ, μ ν리μΌμ΄μ μ λ μμ μ²ν¬λ‘ μ½λ λΆν νλ κ²μ κ³ λ €νμΈμ. μ΄λ μνμ μμ λ³νκ° μ ν리μΌμ΄μ μ ν° λΆλΆμ 리λ λλ§νκ² ν λ νΉν μ€μν©λλ€.
κ²°λ‘
React Context APIλ μν κ΄λ¦¬λ₯Ό μν λ€μ¬λ€λ₯ν λꡬμ λλ€. μ΄λ¬ν κ³ κΈ ν¨ν΄μ μ΄ν΄νκ³ μ μ©ν¨μΌλ‘μ¨ λ³΅μ‘ν μνλ₯Ό ν¨κ³Όμ μΌλ‘ κ΄λ¦¬νκ³ , μ±λ₯μ μ΅μ ννλ©°, λ μ μ§λ³΄μνκΈ° μ½κ³ νμ₯ κ°λ₯ν React μ ν리μΌμ΄μ μ ꡬμΆν μ μμ΅λλ€. νΉμ μꡬμ λ§λ μ¬λ°λ₯Έ ν¨ν΄μ μ ννκ³ μ»¨ν μ€νΈ μ¬μ©μ μ±λ₯μ μν₯μ μ μ€νκ² κ³ λ €νλ κ²μ μμ§ λ§μΈμ.
Reactκ° λ°μ ν¨μ λ°λΌ Context APIλ₯Ό λλ¬μΌ λͺ¨λ² μ¬λ‘λ λ°μ ν κ²μ λλ€. μλ‘μ΄ κΈ°μ κ³Ό λΌμ΄λΈλ¬λ¦¬μ λν μ 보λ₯Ό κ³μ μ νλ©΄ νλ μΉ κ°λ°μ μν κ΄λ¦¬ κ³Όμ λ₯Ό ν΄κ²°ν μ€λΉλ₯Ό κ°μΆ μ μμ΅λλ€. ν¨μ¬ λ μΈλΆνλ λ°μμ±μ μν΄ μκ·Έλ(signals)κ³Ό ν¨κ» 컨ν μ€νΈλ₯Ό μ¬μ©νλ κ²κ³Ό κ°μ μλ‘μ΄ ν¨ν΄μ νμνλ κ²μ κ³ λ €ν΄ λ³΄μΈμ.